/***********************************************************************************
 * 文件名： mcu_uart.c
 * 作者： 刘言
 * 版本： 1
 * 说明：
 *      UART驱动。设计思想：面向对象，MCU应用场景几乎不可能中途添加UART，因此静态定义了所有
 *  的UART端口，不过缓存可以配置是静态定义还是动态创建。
 *      中断入口统一定义在 isr.c 中，需要在中断中调用 Uart_SendComplete 和 
 *  Uart_ReceivedByte 并做好标志位清除。
 *      在中断入口函数处直接调用各个模块事件通知函数，但必须先调用驱动事件通知函数便于先缓存
 *  数据。
 *      支持线程安全。
 * 修改记录：
 * 	2023/4/21: 初版。 刘言。
***********************************************************************************/
#include "mcu_uart.h"
#include "mcu.h"

#if _UART_BUFF_MODE == 0
// 静态定义 USART1
    #ifdef _UART_USE_USART1
        #if _UART_USART1_TX_BUFF_SIZE
static u8 mUart1TxBuff[_UART_USART1_TX_BUFF_SIZE];
static SoftFifo mUart1TxFifo;
        #endif
        #if _UART_USART1_RX_BUFF_SIZE
static u8 mUart1RxBuff[_UART_USART1_RX_BUFF_SIZE];
static SoftFifo mUart1RxFifo;
        #endif
uart_t _UART_USART1_NAME = {
        #if _UART_USART1_TX_BUFF_SIZE
    mUart1TxBuff, &mUart1TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART1_RX_BUFF_SIZE
    mUart1RxBuff, &mUart1RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART1_TX_BUFF_SIZE, _UART_USART1_RX_BUFF_SIZE, false, true, USART1};
    #endif
// 静态定义 USART2
    #ifdef _UART_USE_USART2
        #if _UART_USART2_TX_BUFF_SIZE
static u8 mUart2TxBuff[_UART_USART2_TX_BUFF_SIZE];
static SoftFifo mUart2TxFifo;
        #endif
        #if _UART_USART2_RX_BUFF_SIZE
static u8 mUart2RxBuff[_UART_USART2_RX_BUFF_SIZE];
static SoftFifo mUart2RxFifo;
        #endif
uart_t _UART_USART2_NAME = {
        #if _UART_USART2_TX_BUFF_SIZE
    mUart2TxBuff, &mUart2TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART2_RX_BUFF_SIZE
    mUart2RxBuff, &mUart2RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART2_TX_BUFF_SIZE, _UART_USART2_RX_BUFF_SIZE, false, true, USART2};
    #endif
// 静态定义 USART3
    #ifdef _UART_USE_USART3
        #if _UART_USART3_TX_BUFF_SIZE
static u8 mUart3TxBuff[_UART_USART3_TX_BUFF_SIZE];
static SoftFifo mUart3TxFifo;
        #endif
        #if _UART_USART3_RX_BUFF_SIZE
static u8 mUart3RxBuff[_UART_USART3_RX_BUFF_SIZE];
static SoftFifo mUart3RxFifo;
        #endif
uart_t _UART_USART3_NAME = {
        #if _UART_USART3_TX_BUFF_SIZE
    mUart3TxBuff, &mUart3TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART3_RX_BUFF_SIZE
    mUart3RxBuff, &mUart3RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART3_TX_BUFF_SIZE, _UART_USART3_RX_BUFF_SIZE, false, true, USART3};
    #endif
// 静态定义 UART4
    #ifdef _UART_USE_UART4
        #if _UART_UART4_TX_BUFF_SIZE
static u8 mUart4TxBuff[_UART_UART4_TX_BUFF_SIZE];
static SoftFifo mUart4TxFifo;
        #endif
        #if _UART_UART4_RX_BUFF_SIZE
static u8 mUart4RxBuff[_UART_UART4_RX_BUFF_SIZE];
static SoftFifo mUart4RxFifo;
        #endif
uart_t _UART_UART4_NAME = {
        #if _UART_UART4_TX_BUFF_SIZE
    mUart4TxBuff, &mUart4TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_UART4_RX_BUFF_SIZE
    mUart4RxBuff, &mUart4RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_UART4_TX_BUFF_SIZE, _UART_UART4_RX_BUFF_SIZE, false, true, UART4};
    #endif
// 静态定义 UART5
    #ifdef _UART_USE_UART5
        #if _UART_UART5_TX_BUFF_SIZE
static u8 mUart5TxBuff[_UART_UART5_TX_BUFF_SIZE];
static SoftFifo mUart5TxFifo;
        #endif
        #if _UART_UART5_RX_BUFF_SIZE
static u8 mUart5RxBuff[_UART_UART5_RX_BUFF_SIZE];
static SoftFifo mUart5RxFifo;
        #endif
uart_t _UART_UART5_NAME = {
        #if _UART_UART5_TX_BUFF_SIZE
    mUart5TxBuff, &mUart5TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_UART5_RX_BUFF_SIZE
    mUart5RxBuff, &mUart5RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_UART5_TX_BUFF_SIZE, _UART_UART5_RX_BUFF_SIZE, false, true, UART5};
    #endif
// 静态定义 UART6
    #ifdef _UART_USE_UART6
        #if _UART_UART6_TX_BUFF_SIZE
static u8 mUart6TxBuff[_UART_UART6_TX_BUFF_SIZE];
static SoftFifo mUart6TxFifo;
        #endif
        #if _UART_UART6_RX_BUFF_SIZE
static u8 mUart6RxBuff[_UART_UART6_RX_BUFF_SIZE];
static SoftFifo mUart6RxFifo;
        #endif
uart_t _UART_UART6_NAME = {
        #if _UART_UART6_TX_BUFF_SIZE
    mUart6TxBuff, &mUart6TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_UART6_RX_BUFF_SIZE
    mUart6RxBuff, &mUart6RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_UART6_TX_BUFF_SIZE, _UART_UART6_RX_BUFF_SIZE, false, true, UART6};
    #endif
// 静态定义 UART7
    #ifdef _UART_USE_UART7
        #if _UART_UART7_TX_BUFF_SIZE
static u8 mUart7TxBuff[_UART_UART7_TX_BUFF_SIZE];
static SoftFifo mUart7TxFifo;
        #endif
        #if _UART_UART7_RX_BUFF_SIZE
static u8 mUart7RxBuff[_UART_UART7_RX_BUFF_SIZE];
static SoftFifo mUart7RxFifo;
        #endif
uart_t _UART_UART7_NAME = {
        #if _UART_UART7_TX_BUFF_SIZE
    mUart7TxBuff, &mUart7TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_UART7_RX_BUFF_SIZE
    mUart7RxBuff, &mUart7RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_UART7_TX_BUFF_SIZE, _UART_UART7_RX_BUFF_SIZE, false, true, UART7};
    #endif
#else
    #error "Not supported."
#endif

#if _UART_BLOCKING_MODE == 0 || _UART_BLOCKING_MODE == 2 || _UART_BLOCKING_MODE == 3 || _UART_BLOCKING_MODE == 4
    #error "Not supported."
#endif

/**
 * 中断事件：一个字节发送完毕
*/
void Uart_SendComplete(uart_t *this)
{
    if(this->TxFifo)
    {
        if(SoftFifo_IsEmpty(this->TxFifo))  // 缓存为空， 说明发送任务完毕了
        {
            this->Sending = false;
        }
        else // 还有数据需要发送
        {
            USART_SendData(this->UartInstance, SoftFifo_Read(this->TxFifo));
        }
    }
}

/**
 * 中断事件：一个字节接收完毕(收到一个字节)
*/
void Uart_ReceivedByte(uart_t *this)
{
    if(this->RxFifo)
    {
        bool ret = SoftFifo_Write(this->RxFifo, USART_ReceiveData(this->UartInstance));
        if(ret == false)
        {
            // while(1);   // 缓存溢出了
        }
    }
}

void Uart_Init(uart_t *this, u32 baud)
{
    USART_InitType USART_InitStructure;

    USART_InitStructure.BaudRate            = baud;//115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    USART_Init(this->UartInstance, &USART_InitStructure);

    /* Enable USARTx Receive and Transmit interrupts */
    USART_ConfigInt(this->UartInstance, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(this->UartInstance, USART_INT_TXC, ENABLE); // 注意不能使用TXDE，具体看用户手册的解释

    USART_Enable(this->UartInstance, ENABLE);

    if(this->TxFifo)SoftFifo_Init(this->TxFifo, this->TxBuff, this->TxBuffSize);
    if(this->RxFifo)SoftFifo_Init(this->RxFifo, this->RxBuff, this->RxBuffSize);
}

void Uart_WriteByte(uart_t *this, u8 c)
{
    if(this->TxFifo  && !Mcu_IsIrqMode())
    {
        bool ret = false;
        while(ret == false) // 死等直到写入缓存成功
        {
            // USART_ConfigInt(this->UartInstance, USART_INT_TXC, DISABLE);// 禁止发送完成中断，确保不会在中断中同时操作SoftFifo
            Mcu_DisableInt();
            ret = SoftFifo_Write(this->TxFifo, c);
            // USART_ConfigInt(this->UartInstance, USART_INT_TXC, ENABLE);     // 允许发送完成中断
            Mcu_EnableInt();
        }
        if(this->Sending == false)      // 不在发送中，需要启动发送
        {
            u8 dat;
            this->Sending = true;
            Mcu_DisableInt();
            dat = SoftFifo_Read(this->TxFifo);
            Mcu_EnableInt();
            USART_SendData(this->UartInstance, dat);// 启动发送
        }
    }
    else
    {
        USART_SendData(this->UartInstance, (u16)c);
        while (USART_GetFlagStatus(this->UartInstance, USART_FLAG_TXDE) == RESET);
    }
}

void Uart_Write(uart_t *this, const u8 *dat, size_t size)
{
    while(size--)
	{
		Uart_WriteByte(this, *dat);
		dat++;
	}
}

int Uart_ReadByte(uart_t *this)
{
    if(this->RxFifo)
    {
        int ret;
        // USART_ConfigInt(this->UartInstance, USART_INT_RXDNE, DISABLE);  // 禁止收到数据中断，确保不会在中断中同时操作SoftFifo
        Mcu_DisableInt();
        if(SoftFifo_IsEmpty(this->RxFifo)) ret = -1;
        else ret = SoftFifo_Read(this->RxFifo);
        // USART_ConfigInt(this->UartInstance, USART_INT_RXDNE, ENABLE);     // 允许收到数据中断
        Mcu_EnableInt();
        return ret;
    }
    else    // 没有接收缓存直接返回接收寄存器值
    {
        return USART_ReceiveData(this->UartInstance);
    }
}

int Uart_Read(uart_t *this, u8 *buff, size_t cont)
{
    int read_len = 0;
    if(this->RxFifo)
    {
        while(cont--)
        {
            int ret = Uart_ReadByte(this);
            if(ret == -1) break;
            else buff[read_len] = (u8)ret;
            read_len++;
        }
        return read_len;
    }
    else
    {
        return 0;
    }
}


